home *** CD-ROM | disk | FTP | other *** search
- /*
- * strip TOS executable format files of symbol table info
- * usage: strip [-g] [-k] [-l names] files ...
- *
- * Original version by ++jrb bammi@dsrgsun.ces.cwru.edu
- * (i.e. Jwahar Bammi)
- * Modified to add extra options -g -k and -l by
- * Michal Jaegermann ntomczak@ualtavm.bitnet
- * November 1st, 1990
- *
- * -g keep all global symbols
- * -k keep _stksize symbol, so stack size can be adjusted
- * even for nearly-stripped gcc produced executables
- * -l nms keep all symbols listed in a file 'nms'
- *
- * Modified sources compile both with gcc and Sozobon C
- *
- * Added code to deal correctly with extended symbols produced
- * by -G option of gcc
- * Both -k and -l options convert extended symbols into
- * regular ones.
- *
- * ++jrb 4/25/91:
- * Macroized the code to take care of WORD_ALIGNED cross environments.
- * Minor fixes for a !atari !gcc compiler.
- */
- #include <stdio.h>
- #ifdef atarist
- #ifdef __GNUC__
- # include <stddef.h>
- # include <memory.h>
- # include <unixlib.h>
- #else
- #include <malloc.h>
- extern long lread();
- extern long lwrite();
- extern long lseek();
- #endif
- #endif
-
- #ifdef unix
- # include <strings.h>
- # define lwrite write
- # define lread read
- extern char *malloc(), *realloc();
- #else
- # include <string.h>
- #endif
-
- #include <fcntl.h>
-
- #ifdef __GNUC__
- #define NULL ((void *)0)
- #endif
- #define NEWBUFSIZ 16384L
-
- char mybuf[NEWBUFSIZ];
- char tmpname[128];
-
- #define SYMLEN 8
-
- typedef char symstr_t[SYMLEN];
- symstr_t stklist[] = {{'_', '_', 's', 't', 'k', 's', 'i', 'z',},
- {'\0'}};
-
- #ifdef atarist
- long _stksize = 1L;
- #endif
-
- #ifndef __PROTO
- # if __STDC__ || __cplusplus
- # define __PROTO(s) s
- # else
- # define __PROTO(s) ()
- # endif
- #endif
-
- void usage __PROTO((char *s ));
- int main __PROTO((int argc , char **argv ));
- int strip __PROTO(( char *name,
- symstr_t *nmlist,
- long (*select )(int ,int ,long ,symstr_t *)));
- long copy __PROTO((int from , int to , long bytes ));
- void report __PROTO((char *s ));
- symstr_t *mklist __PROTO((char *fname ));
- long sel_globs __PROTO((int fd , int tfd , long sbytes , symstr_t *nmlist ));
- long sel_listed __PROTO((int fd , int tfd , long sbytes , symstr_t *nmlist ));
- extern char *getenv __PROTO((const char *));
-
- int
- main (argc, argv)
- int argc;
- char **argv;
- {
- int status = 0;
- int flag = -1;
- symstr_t *nmlist = (symstr_t *) 0;
- long (*select) __PROTO((int, int, long, symstr_t *));
- #ifdef atarist
- char *tmpdir;
- register int l;
- #endif
-
- select = (long (*) __PROTO((int, int, long, symstr_t *))) 0;
- /* process arguments */
- while (argv++, --argc) {
- if ('-' != **argv)
- break;
- (*argv)++;
- if ((-1) != flag)
- usage ("only one option at a time is accepted\r\n");
- flag = **argv;
- switch (flag) {
- case 'g':
- select = sel_globs;
- break;
- case 'k':
- nmlist = stklist;
- select = sel_listed;
- break;
- case 'l':
- (*argv)++;
- if ('\0' == **argv) {
- --argc;
- argv++;
- }
- if ((symstr_t *) 0 == (nmlist = mklist (*argv)))
- usage ("cannot create a list of reserved names\r\n");
- select = sel_listed;
- break;
- default:
- usage ("");
- break;
- }
- }
-
- if (argc < 1) {
- usage ("");
- }
-
- #ifdef __GNUC__
- #ifdef atarist
- tmpname[0] = '\0';
- if ((tmpdir = getenv ("TEMP")) != NULL) {
- strcpy (tmpname, tmpdir);
- l = (int) strlen (tmpname) - 1;
- if (tmpname[l] == '\\')
- tmpname[l] = '\0';
- }
- strcat (tmpname, "\\STXXXXXX");
- #else
- strcpy (tmpname, "/tmp/STXXXXXX");
- #endif
-
- mktemp (tmpname);
- #else /* not __GNUC__ */
- # ifdef atarist
- if ((tmpdir = getenv ("TEMP")) != NULL) {
- strcpy (tmpname, tmpdir);
- l = (int) strlen (tmpname) - 1;
- if (tmpname[l] != '\\') {
- l++;
- tmpname[l] = '\\';
- }
- l++;
- }
- else {
- l = 0;
- }
- tmpnam (&tmpname[l]);
- # else
- strcpy (tmpname, "/tmp/STXXXXXX");
- mktemp(tmpname);
- # endif
- #endif /* __GNUC__ */
- do {
- status |= strip (*argv++, nmlist, select);
- } while (--argc > 0);
-
- unlink (tmpname);
- return status;
- }
-
- void
- usage (s)
- char *s;
- {
- report (s);
- report ("Usage: strip [-k] [-l names] [-g] files ...\r\n");
- exit (1);
- }
-
- #if (defined(__GNUC__)) && (!defined(unix))
- #include <st-out.h>
- #else
- /* include relevant fragments of <st-out.h> file directly */
-
- struct aexec {
- short a_magic; /* magic number */
- unsigned long a_text; /* size of text segment */
- unsigned long a_data; /* size of initialized data */
- unsigned long a_bss; /* size of uninitialized data */
- unsigned long a_syms; /* size of symbol table */
- unsigned long a_AZero1; /* always zero */
- unsigned long a_AZero2; /* always zero */
- unsigned short a_isreloc; /* is reloc info present */
- };
- #define CMAGIC 0x601A /* contiguous text */
-
- #define A_BADMAG(x) (((x).a_magic)!=CMAGIC)
-
- /*
- * Format of a symbol table entry
- */
- struct asym
- {
- char a_name[SYMLEN]; /* symbol name */
- unsigned short a_type; /* type flag */
- unsigned long a_value; /* value of this symbol
- (or sdb offset) */
- };
-
- #define A_GLOBL 0x2000 /* global */
- #define A_LNAM 0x0048 /* extended name */
-
- #endif /* __GNUC__ */
-
- #if !__STDC__ && !__cplusplus
- # ifndef offsetof
- # define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
- # endif
- typedef unsigned long size_t;
- #endif
-
- #ifdef WORD_ALIGNED
- # define SIZEOF_AEXEC ((2*sizeof(short)) + (6*sizeof(long)))
- # define SIZEOF_ASYM ((SYMLEN*sizeof(char)) + sizeof(short) + sizeof(long))
- # define SYM_OFFSET (sizeof(short) + (3*sizeof(long)))
- int read_head __PROTO((int fd, struct aexec *a));
- #else
- # define SIZEOF_AEXEC (sizeof(struct aexec))
- # define SIZEOF_ASYM (sizeof(struct asym))
- # define SYM_OFFSET (offsetof (struct aexec, a_syms))
- #endif
-
- int
- strip (name, nmlist, select)
- char *name;
- symstr_t * nmlist;
- long (*select) __PROTO((int, int, long, symstr_t *));
- {
- register int fd;
- register int tfd;
- register long count, rbytes, sbytes;
- long lbytes;
- struct aexec ahead;
-
- if ((fd = open (name, O_RDONLY, 0666)) < 0) {
- perror (name);
- return 2;
- }
- if ((tfd = open (tmpname, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) {
- perror (tmpname);
- close (fd);
- return 4;
- }
- #ifndef WORD_ALIGNED
- if ((count = lread (fd, &ahead, (long) sizeof (ahead)))
- != (long) sizeof (ahead)) {
- #else
- if (read_head (fd, &ahead)) {
- #endif
- perror (name);
- close (tfd);
- close (fd);
- return 8;
- }
- if (A_BADMAG (ahead)) {
- report (name);
- report (": Bad Magic number\r\n");
- close (tfd);
- close (fd);
- return 0x10;
- }
- sbytes = ahead.a_syms;
- if (0L == sbytes) {
- report (name);
- report (": Already Stripped\r\n");
- close (tfd);
- close (fd);
- return 0x20;
- }
- if (lseek (fd, 0L, 0) < 0) {
- report (name);
- report (": seek error\r\n");
- close (tfd);
- close (fd);
- return 0x40;
- }
- count = SIZEOF_AEXEC + ahead.a_text + ahead.a_data;
- if (copy (fd, tfd, count) != count) {
- close (tfd);
- close (fd);
- return 0x80;
- }
- if ((long(*)())0 == select) { /* remove whole symbol table */
- lbytes = 0L;
- if (lseek (fd, sbytes, 1) < 0) {
- report (name);
- report (": seek error\r\n");
- close (tfd);
- close (fd);
- return 0x100;
- }
- }
- else {
- lbytes = ( *select )(fd, tfd, sbytes, nmlist);
- }
- if ((rbytes = copy (fd, tfd, 0x7fffffffL)) < 0) {
- close (tfd);
- close (fd);
- return 0x200;
- }
- if (lseek (tfd, (long)(SYM_OFFSET), 0) < 0) {
- close (tfd);
- close (fd);
- return 0x400;
- }
- if (lwrite (tfd, &lbytes, (long)sizeof (lbytes)) !=
- (long) sizeof (lbytes)) {
- close (tfd);
- close (fd);
- return 0x800;
- }
- close (tfd);
- close (fd);
- if (rename(tmpname, name) == 0) return 0; /* try to rename it */
- if ((fd = open (name, O_WRONLY | O_TRUNC | O_CREAT, 0666)) < 0) {
- perror (name);
- return 0x1000;
- }
- if ((tfd = open (tmpname, O_RDONLY, 0666)) < 0) {
- perror (tmpname);
- close (fd);
- return 0x2000;
- }
-
- count = SIZEOF_AEXEC + ahead.a_text + ahead.a_data + rbytes + lbytes;
- if (copy (tfd, fd, count) != count) {
- close (tfd);
- close (fd);
- return 0x4000;
- }
- close (tfd);
- close (fd);
- return 0;
- }
-
- /*
- * copy from, to in NEWBUFSIZ chunks upto bytes or EOF whichever occurs first
- * returns # of bytes copied
- */
- long
- copy (from, to, bytes)
- int from, to;
- long bytes;
- {
- register long todo, done = 0L, remaining = bytes, actual;
-
- while (done != bytes) {
- todo = (remaining > NEWBUFSIZ) ? NEWBUFSIZ : remaining;
- if ((actual = lread (from, mybuf, todo)) != todo) {
- if (actual < 0) {
- report ("Error Reading\r\n");
- return -done;
- }
- }
- if (lwrite (to, mybuf, actual) != actual) {
- report ("Error Writing\r\n");
- return -done;
- }
- done += actual;
- if (actual != todo) /* eof reached */
- return done;
- remaining -= actual;
- }
- return done;
- }
-
- void
- report (s)
- char * s;
- {
- lwrite (2, s, (long) strlen (s));
- }
-
- /*
- * Given a name of a file with reserved symbols create an array of
- * reserved symbol names. To terminate create an entry which starts
- * with a null character.
- */
-
- #define LBUFSIZE 128
- #define NMSTEP 10
-
- symstr_t *
- mklist (fname)
- char * fname;
- {
- FILE *fp;
- symstr_t *list = (symstr_t *) 0;
- int left = 0;
- int pos = 0;
- int i;
- size_t max_size = 1;
- char lbuf[LBUFSIZE];
- char *in, *out;
-
- if (NULL == (fp = fopen (fname, "r"))) {
- report (fname);
- report (" -- ");
- usage ("cannot open this file\r\n");
- }
-
- while (NULL != fgets (lbuf, LBUFSIZE, fp)) {
- if (0 == left) {
- max_size += NMSTEP;
- if ((symstr_t *)0 == list) {
- list = (symstr_t *) malloc ( max_size * sizeof (symstr_t));
- }
- else {
- list = (symstr_t *) realloc ((void *) list,
- max_size * sizeof (symstr_t));
-
- }
- if ((symstr_t *)0 == list) {
- report ("out of memory making symbol list\r\n");
- exit (-3);
- }
- left = NMSTEP;
- }
- /* strip all leading white space */
- in = lbuf;
- while (' ' == *in || '\t' == *in)
- in++;
- if ('\n' == *in)
- continue; /* empty line - skip it */
- out = &list[pos][0];
- for (i = SYMLEN; i > 0; --i) {
- if ('\n' == *in || ' ' == *in || '\t' == *in) {
- *out = '\0';
- break;
- }
- *out++ = *in++;
- }
- pos++;
- --left;
- } /* while */
- if ((symstr_t *)0 != list) {
- list[pos][0] = '\0'; /* terminate created list */
- }
- return (list);
- }
-
- /*
- * From a file handle fd to a file handle tfd copy up to 'sbytes' bytes
- * of a symbol table selecting only those symbols which have A_GLOBL
- * flag set. Table nmlist is not really used, but is here for a uniform
- * interface. Returns a number of bytes copied.
- */
- long
- sel_globs (fd, tfd, sbytes, nmlist)
- int fd, tfd;
- long sbytes;
- symstr_t * nmlist;
- {
- long lbytes = 0;
- struct asym cur_sym;
- int cont = 0;
-
- while (sbytes) {
- if ((long)SIZEOF_ASYM != lread (fd, &cur_sym,
- (long)SIZEOF_ASYM)) {
- report ("error on reading symbol table\r\n");
- break;
- }
- if (0 == cont) { /* if we are not dealing with the second part */
- cont = (0 != (cur_sym.a_type & A_LNAM));
- if (cur_sym.a_type & A_GLOBL) {
- cont = -cont;
- if ((long)SIZEOF_ASYM != lwrite (tfd, &cur_sym,
- (long)SIZEOF_ASYM)) {
- report ("error on writing symbol table\r\n");
- break;
- }
- lbytes += SIZEOF_ASYM;
- }
- }
- else { /* this was an extended symbol */
- if (cont < 0) { /* if global then write */
- if ((long)SIZEOF_ASYM != lwrite (tfd, &cur_sym,
- (long)SIZEOF_ASYM)) {
- report ("error on writing symbol table\r\n");
- break;
- }
- lbytes += SIZEOF_ASYM;
- }
- cont = 0;
- }
- sbytes -= SIZEOF_ASYM;
- }
- return (lbytes);
- }
-
- /*
- * From a file handle fd to a file handle tfd copy up to 'sbytes' bytes
- * of a symbol table selecting only those symbols which are on nmlist.
- * Free nmlist if different from a default global one.
- * Returns a number of bytes copied.
- */
- long
- sel_listed (fd, tfd, sbytes, nmlist)
- int fd, tfd;
- long sbytes;
- symstr_t * nmlist;
- {
- long lbytes = 0;
- symstr_t *kname;
- struct asym cur_sym, spare;
-
- if ((symstr_t *) 0 == nmlist)
- return (0L);
-
- while (sbytes) {
- if ((long)SIZEOF_ASYM != lread (fd, &cur_sym,
- (long) SIZEOF_ASYM)) {
- report ("error on reading symbol table\r\n");
- break;
- }
- for (kname = nmlist; '\0' != **kname; kname++) {
- if (0 == strncmp (&(*kname)[0], &cur_sym.a_name[0], SYMLEN)) {
- if (A_LNAM & cur_sym.a_type) { /* if extended */
- cur_sym.a_type ^= A_LNAM;
- if ((long)SIZEOF_ASYM != lread (fd, &spare,
- (long)SIZEOF_ASYM)) {
- report ("error on reading symbol table\r\n");
- goto leave; /* skip two loop levels */
- }
- sbytes -= SIZEOF_ASYM;
- }
- if ((long)SIZEOF_ASYM != lwrite (tfd, &cur_sym,
- (long)SIZEOF_ASYM)) {
- report ("error on writing symbol table\r\n");
- goto leave;
- }
- lbytes += SIZEOF_ASYM;
- break;
- }
- } /* for */
- sbytes -= SIZEOF_ASYM;
- } /* while */
- leave:
- if (nmlist != stklist) {
- free (nmlist);
- nmlist = (symstr_t *) 0;
- }
- return (lbytes);
- }
-
- #ifdef WORD_ALIGNED
- /*
- * read header -- return !0 on err
- */
- #define ck_read(fd, addr, siz) \
- if((long)siz != lread(fd, addr, (long)siz)) return !0;
-
- int read_head (fd, a)
- int fd;
- struct aexec *a;
- {
- ck_read(fd, &a->a_magic, sizeof(a->a_magic));
- ck_read(fd, &a->a_text, sizeof(a->a_text));
- ck_read(fd, &a->a_data, sizeof(a->a_data));
- ck_read(fd, &a->a_bss, sizeof(a->a_bss));
- ck_read(fd, &a->a_syms, sizeof(a->a_syms));
- ck_read(fd, &a->a_AZero1, sizeof(a->a_AZero1));
- ck_read(fd, &a->a_AZero2, sizeof(a->a_AZero2));
- ck_read(fd, &a->a_isreloc, sizeof(a->a_isreloc));
-
- return 0;
- }
- #endif
-